#include <string.h>
#include <errno.h>
#include <iostream>
#include <stdio.h>
using namespace std;
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>

#define NUM 10

typedef void(*func)();

func function[NUM + 1] = {nullptr};

void Download()
{
    cout << "download..." << endl;
}

void Log()
{
    cout << "log..." << endl;
}

void Flush()
{
    cout << "flush..." << endl;
}

void functionRegister(func h[], func f)
{
    int i = 0; 
    for(; i < NUM; i++)
    {
        if(h[i] == nullptr)
        {
            break;
        }
    }
    if(i == NUM)
    {
        return;
    }
    else
    {
        h[i] = f;
        h[i + 1] = nullptr;
    }
}

int main()
{
    functionRegister(function, Download);
    functionRegister(function, Log);
    functionRegister(function, Flush);
    pid_t id = fork();
    if(id == 0)
    {
        int n = 5;
        while(1)
        {
        printf("我是子进程, pid:%d\n", getpid());
        sleep(1);
        }
        exit(10);
    }

    while(1)
    {
        int status = 0;
        //非阻塞调用——第三个参数是opetion，立即返回值如果没有子进程退出
        pid_t rid = waitpid(id, &status, WNOHANG);
        if(rid > 0)
        {
            //杀死进程
            printf("wait success, rid:%d, exit code: %d, exit signal:%d\n", rid, WEXITSTATUS(status), status & 0x7F);
            break;
        }
        else if (rid == 0)
        {
            //未杀死子进程
            //进行其他工作
            for(int i = 0; function[i]; i++)
            {
                //回调函数
                function[i]();
            }
            printf("本轮调用结束，子进程没有退出\n");
            sleep(1);
        }
        else
        {
            printf("等待出错\n");
            break;
        }
    }
   // //pid_t rid = wait(NULL);//等待任意个退出的子进程，返回结果就是子进程的pid
   // int status = 0;
   // //waitpid返回值，>0表示等待结束，=0表示调用结束但是子进程没有退出，小于0失败
   // //非阻塞调用，可以让等待方做做自己的事情（Non Lock)
   // pid_t rid = waitpid(id, &status, 0);//系统调用，阻塞调用，直到子进程返回，
   //                                     //相反的就是非阻塞轮询，不断检测，
   //                                     //采用循环的方式，直到等待结束
   //                                     //子进程内部有exit_code和exit_signal，
   //                                     //父进程通过系统调用将以上两者放到自己
   //                                     //内部的status中
   // if(rid > 0)//等待成功后，僵尸进程结束
   // {
   //     //等待成功
   //     if(WIFEXITED(status))

   //     //printf("wait success, rid:%d, exit code: %d, exit signal:%d\n", rid, (status >> 8) & 0xFF, status & 0x7F);
   //     printf("wait success, rid:%d, exit code: %d, exit signal:%d\n", rid, WEXITSTATUS(status), status & 0x7F);
   //     //取退出码是后八位，取终止信号是前七位
   //     else
   //     {
   //         printf("进程退出异常\n");
   //     }
   // }
   // else 
   // {
   //     printf("wait fail:%d, %s\n", errno, strerror(errno));
   // }
    return 0;
    //waitpid的第二个参数：输出型参数，了解子进程运行情况如何（通过进程退出码，即
    //main函数返回值）status包括的信息有：高16位不使用
    //正常终止：
    //|----------------|----------------|低
    //    退出状态             不用
    //
    //被信号所杀：
    //|————————————————|—|——————————————|低
    //     未用      core dump   终止信号

    //cout << "begin" << endl;
    //exit(40);
    //cout << "end" << endl;
    


    //一旦出现异常，退出码就没有意义了
    //int i = 10;
    //exit(123);
    //i /= 0;
    //return 89;
    //for(int i = 0; i < 134; i++)
    //{
    //    printf("i : %s\n", strerror(i));
    //}
    //FILE* pf = fopen("code.cpp", "r");
    //if(pf == nullptr)
    //{
    //    return errno;
    //    //返回相应的错误编号
    //}
    //cout << "王家乐" << endl;
    return 0;
}
